package com.hvgroup.modules.sanic.util;

import com.hvgroup.utils.StringUtils;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @migratedFrom Python
 * @source common/minio_util.py
 * @originalClass MinioUtils
 * @description MinIO 工具类，提供桶校验、文件上传和预签名 URL 功能
 */
@Slf4j
@Component
public class MinioUtil {

    @Value("${minio.endpoint}")
    private String endpoint;

    @Value("${minio.access-key}")
    private String accessKey;

    @Value("${minio.secret-key}")
    private String secretKey;

    /**
     * 初始化 MinIO 客户端
     */
    private MinioClient getClient() {
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }

    /**
     * 检查指定桶是否存在，不存在则创建
     */
    public void ensureBucket(String bucketName) {
        try {
            MinioClient client = getClient();
            boolean exists = client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exists) {
                client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                log.info("Bucket '{}' created.", bucketName);
            } else {
                log.info("Bucket '{}' already exists.", bucketName);
            }
        } catch (Exception e) {
            log.error("Error ensuring bucket exists: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to ensure bucket", e);
        }
    }

    /**
     * 上传文件流到 MinIO
     *
     * @param stream      输入流
     * @param size        文件大小
     * @param bucketName  桶名
     * @param fileName    文件名
     * @param contentType 文件类型
     * @return 返回上传后的文件名（对象键）
     */
    public String uploadFile(InputStream stream, long size, String bucketName, String fileName, String contentType) {
        try {
            MinioClient client = getClient();
            ensureBucket(bucketName);

            if (StringUtils.isEmpty(fileName)) {
                fileName = UUID.randomUUID().toString();
            }

            client.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .stream(stream, size, -1)
                            .contentType(contentType)
                            .build()
            );

            log.info("File uploaded successfully with key: {}", fileName);
            return fileName;
        } catch (Exception e) {
            log.error("Error uploading file: {}", e.getMessage(), e);
            throw new RuntimeException("File upload failed", e);
        }
    }

    /**
     * 支持从 byte[] 上传文件（常用于 Multipart 文件场景）
     */
    public String uploadFile(byte[] data, String contentType, String bucketName, String fileName) {
        try (ByteArrayInputStream stream = new ByteArrayInputStream(data)) {
            long size = data.length;
            return uploadFile(stream, size, bucketName, fileName, contentType);
        } catch (Exception e) {
            log.error("Error uploading byte[] file", e);
            throw new RuntimeException("Failed to upload file", e);
        }
    }

    /**
     * 获取预签名下载 URL
     *
     * @param bucketName 桶名
     * @param objectKey  对象名（文件键）
     * @return 预签名 URL（含过期时间）
     */
    public String getPresignedUrl(String bucketName, String objectKey) {
        try {
            MinioClient client = getClient();
            return client.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(bucketName)
                            .object(objectKey)
                            .expiry(7, TimeUnit.DAYS)
                            .build()
            );
        } catch (Exception e) {
            log.error("Error generating presigned URL: {}", e.getMessage(), e);
            throw new RuntimeException("Presigned URL generation failed", e);
        }
    }

    /**
     * 简洁别名：获取文件访问 URL
     */
    public String getFileUrlByKey(String objectKey) {
        return getPresignedUrl("filedata", objectKey);
    }
}
